//
//  CTVNavigationManager.m
//  Channltv
//
//  Created by Bruno Keymolen on 14/11/07.
//  Copyright 2007 channl.tv. All rights reserved.
//

#import "CTVNavigationManager.h"
#import "CTV.h"

@implementation CTVNavigationManager


+(CTVNavigationManager*)GetInstance {
	static id _CTVSingleton = nil;
	if (_CTVSingleton == nil) {
		_CTVSingleton = [self new];
		[_CTVSingleton _init];
	}	
    return _CTVSingleton;
}

-(void)_init{
	//Init Lock
	m_syncLock = [[NSRecursiveLock alloc] init];
}

-(void)setEntryPoint:(CTVClip*)clip{
	[self _setCurrentClip:clip]; //@TODO:CHECK
//	[self __setCurrentClip:clip];
}


-(CTVClip*)currentClip{
	return m_currentClip;
}

-(CTVChannel*)currentChannel{
	return (CTVChannel*)[m_currentClip pChannel];
}


-(CTVClip*)nextClip{
	CTVClip* clip = nil;
	[m_syncLock lock];
	if(m_currentClip != nil){
		clip = [[m_currentClip pChannel] nextClipToPlay];
		[self _setCurrentClip:clip];
	}
	[m_syncLock unlock];
	
	return clip;
}

-(CTVClip*)prevClip{
	CTVClip* clip = nil;
	[m_syncLock lock];
	if(m_currentClip != nil){
		clip = [[m_currentClip pChannel] prevClipToPlay];
		[self _setCurrentClip:clip];
	}
	[m_syncLock unlock];
	
	return clip;
}


-(CTVChannel*)nextChannel{
	[m_syncLock lock];

	CTVChannel* nextChannel;
	nextChannel = [self getDistanceFromChannel:nil distance:1];
	if(nextChannel){
		[self __setCurrentClip:[nextChannel currentClipToPlay]];
	}
	[m_syncLock unlock];
	
	return [m_currentClip pChannel];
}


-(CTVChannel*)prevChannel{
	CTVChannel* prevChannel;
	[m_syncLock lock];
	prevChannel = [self getDistanceFromChannel:nil distance:-1];
	if(prevChannel){
		[self __setCurrentClip:[prevChannel currentClipToPlay]];
	}
	[m_syncLock unlock];
	
	return [m_currentClip pChannel];
}

-(CTVChannel*)getDistanceFromChannel:(CTVChannel*)channel distance:(signed int)distance{
	CTVChannel* thisChannel;
	int index;
	int searchIndex;
	int channelCount;

	[m_syncLock lock];
	
	distance = -distance;
	
	if(channel == nil){
		channel = [m_currentClip pChannel];
	}
	
	//Channel collection (rootchannels*->channels*->clips*)
	CTVRootChannel* root = [channel pRootChannel];

	channelCount = [[root channels] count] -1; //-1 to make it 0 based

	//Locate channel in rootchannel, do this by ID to overcome object pointer mismatches as a result of sync
	index = [[[root channels] allKeys] indexOfObject:[channel url]];	
	if(index == NSNotFound){
		NSLog(@"Channel not found. %@, %@", [channel name], [channel url]);
		index = 0;
	}
	
	if(abs(distance) >= channelCount){
		distance = distance % channelCount; 
	}

	searchIndex = index + distance;

	if(searchIndex >= channelCount){
		searchIndex = searchIndex - channelCount;
	}
	if(searchIndex < 0){
		searchIndex = channelCount + searchIndex;
	}

	thisChannel = [[[root channels] allValues] objectAtIndex:searchIndex];		

	[m_syncLock unlock];

	return thisChannel;
}



// Private
-(void)_setCurrentClip:(CTVClip*)clip{
	BOOL otherClip;

	CTVChannel* channel = [clip pChannel];

	if(![[[channel watchPoint] clipID] isEqualToString:[clip clipID]]){
		otherClip = TRUE;
	} 
		
	if([[m_currentClip getUrl] isEqualToString:[clip getUrl]]){
		otherClip = FALSE;
	}else{
		otherClip = TRUE;
	}
	[self __setCurrentClip:clip];	
	//Update the watchpoint in the channel
	[[m_currentClip pChannel] updateWatchPointWithClip:m_currentClip];
	//Reset watchpoint minutes (only if we change the clip in a channel)
	if(otherClip == TRUE){
		CTVChannel* channel = [m_currentClip pChannel];
		[[channel watchPoint] setOffset:0.0f];
	}
}


-(void)__setCurrentClip:(CTVClip*)clip{
	if(m_currentClip)[m_currentClip release];
	m_currentClip = clip;
	[m_currentClip retain];
}




@end
